/**
 * Created by hjqi on 2016/5/1.
 */

var httpRequest = require('../common/httpRequest').httpRequest;

var Common = require('../common/common');
var myRet = Common.myReturn;
var emptyPromise = Common.emptyPromise;
var logger = require('../log4js/log4js').logger('storageBase');
var Q = require('q'),
    result = Q('begin');
var config = require('../config/config').config;
var storageMetaInfoDB = require('../../db/storageMetaInfoDB');
var _storageinfo = new storageMetaInfoDB();
module.exports = storageBase;

function storageBase(){
}

storageBase.prototype.createNamespace = function(ns){}

storageBase.prototype.createVolume = function(ns,volume,policy){}

storageBase.prototype.createVolumeImpl = function(ns,vol,policy){
    var _rollback_stack = [];
    var _self = this;
    return new Promise(function (resolve, reject) {
        //check if exist volume exist in glusterfs
        var _volId = ns + '-' + vol.volumeName;
        _self.isExistVolumeInServer(_volId,ns).then(function(ret){

            /**
             *  if exist,check policy
             *      1) if reuse , return success
             *      2) if need clean files, delete files in volume and return success
             *      3) if default , throw exist error
             *
             */
            if(ret.ret === true){
                logger.debug("found ["+_volId+"] exist in storage server");
                if(policy === Common.PVPolicy.REUSE){
                    return emptyPromise(myRet(true,undefined,policy));
                }else if(policy === Common.PVPolicy.CLEANFILES){
                    //TODO  clean files in volume
                    return emptyPromise(myRet(false,undefined,policy));
                }
                else{
                    reject(myRet(false,"volume ["+vol.volumeName+"] already exist"));
                }
            }else{
                logger.debug("["+_volId+"] need to create..");
                //if not , create it
                vol.volumeSize = vol.volumeSize || 1024;
                return _self.createVolumeReq(ns,_volId,vol.volumeSize);
            }
        }).then(function (ret) {

            //create successful , set volume metainfo in db
            if (ret.ret === true) {

                vol.namespace = ns;
                vol.volumeId = _volId;
                if(vol.volumeSize){

                }
                //rollback stack
                _rollback_stack.push({
                    fn: _self.deleteVolume,
                    args: [ns, vol]
                });

                var _data = {};
                _data.name = vol.volumeName;
                _data.volumeId = _volId;
                _data.namespace = ns;
                _data.mountAppName = '';
                _data.mountNodeName = '';
                _data.mountName = vol.mountName;
                _data.size = vol.volumeSize;
                _data.type = config.storage.type;
                var d=new Date();
                _data.createDate=d;
                _storageinfo.insert(null, _data, function (err) {
                    if (err){
                        var _retmsg = "["+_volId+"] insert storage table happen error:"+err.message;
                        logger.error(_retmsg);
                        reject(myRet(false,_retmsg));
                    }
                    else{
                        resolve(myRet(true,undefined,_data));
                    }
                });
            }
            //create failed ,and return error info
            else {
                if(ret.data === Common.PVPolicy.REUSE || ret.data === Common.PVPolicy.CLEANFILES){
                    var _query = {
                        namespace:ns,
                        volumeId:_volId
                    };
                    _storageinfo.getWithParam(null, _query, function (err,data) {
                        if (err){
                            var _retmsg = "["+_volId+"] query storage table happen error:"+err.message;
                            logger.error(_retmsg);
                            reject(myRet(false,_retmsg));
                        }
                        else{
                            if(data.length > 0)
                                resolve(myRet(true,undefined,data[0]));
                            else
                                reject(myRet(false,"["+_volId+"] can't find storage info in db"));
                        }
                    });
                }else{
                    var _retmsg = "create volumn error";
                    reject(myRet(false,_retmsg));
                }

            }
        }).catch(function (err) {

            /*
             *  catch all other error happened
             */

            //rollback
            rollback(_self, _rollback_stack).then(function () {
                reject(err);
            }).catch(function (err) {
                //rollback happened error
                logger.info("create volume rollback err:"+JSON.stringify(err));
                reject(err);
            });

        });
    });
}

storageBase.prototype.createVolumeReq = function(ns,volumeId,size){}

storageBase.prototype.isExistVolumeInServer = function(volumeId,ns){}

storageBase.prototype.deleteVolume = function(volume){}

storageBase.prototype.deleteVolumeForce = function(ns,volumeId){
    var self = this;
    return new Promise(function (resolve, reject) {

        //check if exist volume exist in volume  server
        self.isExistVolumeInServer(volumeId,ns).then(function(ret){
            //if exist , delete it
            if(ret.ret){
                return self.deleteVolume({namespace:ns,volumeId:volumeId});
            }
            //not exist ,nothing to do and go to next step
            else{
                return new Promise(function (_resolve,_reject) {
                    _resolve(myRet(true)) ;
                });
            }
        }).then(function(ret){
                //if delete volume successful, delete db record
                if (ret.ret === true) {
                    _storageinfo.delWithParam(null,{namespace:ns,volumeId:volumeId},function(err){
                        if(err){
                            reject(myRet(false,err.message));
                        }
                        else{
                            resolve(myRet(true));
                        }
                    });
                }
                //if delete failed,throw error
                else{
                    reject(ret);
                }
            })
            //catch delete volume exception
            .catch(function(err){
                reject(err);
            });

    });
}

storageBase.prototype._usedImage = function (volume) {}
storageBase.prototype.IsExistVolSvc = function(ns,volumeId){
    return new Promise(function (resolve, reject) {
        _storageinfo.getWithParam(null,{namespace:ns,volumeId:volumeId},function(err,rets){

            if(err){
                reject({
                    ret:false,
                    data:err
                })
            }
            else{
                resolve({
                    ret:true,
                    data:rets[0]
                });
            }
        });
    });
}

storageBase.prototype.DelInfoFromDB = function(ns,volumeId){
    return new Promise(function (resolve, reject) {
        _storageinfo.delWithParam(null, {namespace: ns, volumeId: volumeId}, function (err) {
            if (err) {
                reject(myRet(false,err.message));
            }
            else {
                resolve(myRet(true));
            }
        });
    });
}

function rollback(ctx,stack){

    return new Promise(function(resolve, reject){
        stack.reverse().forEach(function(exec){
            var fn = exec.fn;
            result = result.then(fn.apply(ctx,exec.args));
        });


        result.then(function (finalText) {
                resolve(true);
            })
            .catch(function (error) {
                reject(error);
            })
            .done();
    });

}
